#include <QFile>
#include <QDebug>
#include <QRadioButton>
#include <QFileDialog>
#include "taskcontroller.h"

TaskController::TaskController(int tScreen, bool vDesktop, int pScreenNo, QDesktopWidget *dWidget)
{
    screensLabel = NULL;
    showClock = NULL;
    showStructedLight = NULL;
//    radioGroup = NULL;
    mainVLayout = NULL;
    taskVLayout = NULL;
    sLightHLayout = NULL;
    dCircleHLayout = NULL;

    myTimer = NULL;
//    mySCTimer = NULL;
    colorList = NULL;
    widthList = NULL;

    fullscrClockList = NULL;
    fullscrSLightList = NULL;
    fullscrCircleList = NULL;
    fullscrImageList = NULL;
    scanCircleList = NULL;

    totalScreen = tScreen;
    isVirtualDesktop = vDesktop;
    primeScreen = pScreenNo;
    desktop = dWidget;

    initWindow();
}

void TaskController::initWindow()
{
    //Set the display status string
    QString vDesktopString;
    if (true == isVirtualDesktop) vDesktopString = "virtual-desktop";
    else vDesktopString = "non-virtual-desktop";
    QString displayStatus = tr("%1 display(s) working under %2 mode, the primary Screen is No.%3")
                            .arg(totalScreen).arg(vDesktopString).arg(primeScreen);

    //Construct the buttons and labels
    screensLabel = new QLabel(displayStatus);
    showClock = new QPushButton(tr("Show Clock"));
    showStructedLight =  new QPushButton(tr("Show Structed Light"));
    drawCircle = new QPushButton(tr("Draw Circle"));
    drawRing = new QPushButton(tr("Draw Ring"));

    //the Structet light configure group
//    radioGroup = new QButtonGroup;
//    QRadioButton * radioButton1 = new QRadioButton(tr("Vertical"));
//    radioGroup->addButton(radioButton1);
//    QRadioButton * radioButton2 = new QRadioButton(tr("Horizontal"));
//    radioGroup->addButton(radioButton2);

    xInput = new QLineEdit(tr("100"));
    yInput = new QLineEdit(tr("100"));
    radInput = new QLineEdit(tr("50"));
    rInput = new QLineEdit(tr("255"));
    gInput = new QLineEdit(tr("255"));
    bInput = new QLineEdit(tr("255"));
    widthInput = new QLineEdit(tr("1"));

    //Construct the layouts
    mainVLayout = new QVBoxLayout;
    taskVLayout = new QVBoxLayout;
    sLightHLayout = new QHBoxLayout;
    dCircleHLayout = new QHBoxLayout;

    //DrawCircle layouts
    dcLocVLayout = new QVBoxLayout;
    lineVLayout = new QVBoxLayout;
    dcButVLayout = new QVBoxLayout;

    locXHLayout = new QHBoxLayout;
    locYHLayout = new QHBoxLayout;
    radHLayout = new QHBoxLayout;

    redHLayout = new QHBoxLayout;
    greenHLayout = new QHBoxLayout;
    blueHLayout = new QHBoxLayout;
    widthHLayout = new QHBoxLayout;

    sLightHLayout->addWidget(showStructedLight);
//    sLightHLayout->addWidget(radioGroup);

    locXHLayout->addWidget(new QLabel(tr("X:")));
    locXHLayout->addWidget(xInput);
    locYHLayout->addWidget(new QLabel(tr("Y:")));
    locYHLayout->addWidget(yInput);
    radHLayout->addWidget(new QLabel(tr("Radius:")));
    radHLayout->addWidget(radInput);

    redHLayout->addWidget(new QLabel(tr("Red:")));
    redHLayout->addWidget(rInput);
    greenHLayout->addWidget(new QLabel(tr("Green:")));
    greenHLayout->addWidget(gInput);
    blueHLayout->addWidget(new QLabel(tr("Blue:")));
    blueHLayout->addWidget(bInput);
    widthHLayout->addWidget(new QLabel(tr("Line Width:")));
    widthHLayout->addWidget(widthInput);

    dcButVLayout->addWidget(drawCircle);
    dcButVLayout->addWidget(drawRing);
    
    dcLocVLayout->addLayout(locXHLayout);
    dcLocVLayout->addLayout(locYHLayout);
    dcLocVLayout->addLayout(radHLayout);

    lineVLayout->addLayout(redHLayout);
    lineVLayout->addLayout(greenHLayout);
    lineVLayout->addLayout(blueHLayout);
    lineVLayout->addLayout(widthHLayout);

    dCircleHLayout->addLayout(dcLocVLayout);
    dCircleHLayout->addLayout(lineVLayout);
    dCircleHLayout->addLayout(dcButVLayout);
    //DrawCircle layouts end

    //DrawImage layouts
    dImageVLayout = new QVBoxLayout;
    drawDImage = new QPushButton(tr("Draw Default Image"));
    drawSImage = new QPushButton(tr("Draw Selected Image"));
    dImageVLayout->addWidget(drawDImage);
    dImageVLayout->addWidget(drawSImage);
    //DrawImage layouts end

    //Scaning Circle layouts
    sCRadiusHLayout = new QHBoxLayout;
    sCRadiusHLayout->addWidget(new QLabel(tr("Radius:")));
    sCirRadInput = new QLineEdit(tr("100"));
    sCRadiusHLayout->addWidget(sCirRadInput);

    sCLWHLayout = new QHBoxLayout;
    sCLWHLayout->addWidget(new QLabel(tr("Line Width:")));
    sCirLWInput = new QLineEdit(tr("5"));
    sCLWHLayout->addWidget(sCirLWInput);

    sInvHLayout = new QHBoxLayout;
    sInvHLayout->addWidget(new QLabel(tr("Interval(Sec):")));
    sCirInvInput = new QLineEdit(tr("0.1"));
    sInvHLayout->addWidget(sCirInvInput);

    scaCirParVLayout = new QVBoxLayout;
    scaCirParVLayout->addLayout(sCRadiusHLayout);
    scaCirParVLayout->addLayout(sCLWHLayout);
    scaCirParVLayout->addLayout(sInvHLayout);

    sCRHLayout = new QHBoxLayout;
    sCRHLayout->addWidget(new QLabel(tr("Red:")));
    sCirRInput = new QLineEdit(tr("255"));
    sCRHLayout->addWidget(sCirRInput);

    sCGHLayout = new QHBoxLayout;
    sCGHLayout->addWidget(new QLabel(tr("Green:")));
    sCirGInput = new QLineEdit(tr("255"));
    sCGHLayout->addWidget(sCirGInput);

    sCBHLayout = new QHBoxLayout;
    sCBHLayout->addWidget(new QLabel(tr("Blue:")));
    sCirBInput = new QLineEdit(tr("255"));
    sCBHLayout->addWidget(sCirBInput);

    scaCirColorVLayout = new QVBoxLayout;
    scaCirColorVLayout->addLayout(sCRHLayout);
    scaCirColorVLayout->addLayout(sCGHLayout);
    scaCirColorVLayout->addLayout(sCBHLayout);

    scaCircleHLayout = new QHBoxLayout;
    scaCircleHLayout->addLayout(scaCirParVLayout);
    scaCircleHLayout->addLayout(scaCirColorVLayout);
    startScaCircle = new QPushButton(tr("Start Scan"));
    scaCircleHLayout->addWidget(startScaCircle);
    //Scaning Circle layouts end

    //Organize the interface
    QLabel * newLabel = new QLabel(tr("------------Clock------------"));
    newLabel->setAlignment(Qt::AlignCenter);
    taskVLayout->addWidget(newLabel);
    taskVLayout->addWidget(showClock);

    newLabel = new QLabel(tr("------------Structured Light------------"));
    newLabel->setAlignment(Qt::AlignCenter);
    taskVLayout->addWidget(newLabel);
    taskVLayout->addLayout(sLightHLayout);

    newLabel = new QLabel(tr("------------Circle------------"));
    newLabel->setAlignment(Qt::AlignCenter);
    taskVLayout->addWidget(newLabel);
    taskVLayout->addLayout(dCircleHLayout);

    newLabel = new QLabel(tr("------------Image------------"));
    newLabel->setAlignment(Qt::AlignCenter);
    taskVLayout->addWidget(newLabel);
    taskVLayout->addLayout(dImageVLayout);

    newLabel = new QLabel(tr("------------Scaning Circle------------"));
    newLabel->setAlignment(Qt::AlignCenter);
    taskVLayout->addWidget(newLabel);
    taskVLayout->addLayout(scaCircleHLayout);

    closeAll = new QPushButton(tr("Close All"));
    newLabel = new QLabel(tr("------------Close All------------"));
    newLabel->setAlignment(Qt::AlignCenter);
    taskVLayout->addWidget(newLabel);
    taskVLayout->addWidget(closeAll);

    mainVLayout->addWidget(screensLabel);
    mainVLayout->addLayout(taskVLayout);
    this->setLayout(mainVLayout);

    //Connect the signals and slots
    connect(showClock, SIGNAL(clicked()), SLOT(onShowClock()));
    connect(showStructedLight, SIGNAL(clicked()), SLOT(onShowStructedLight()));
    connect(drawCircle, SIGNAL(clicked()), SLOT(onDrawCircle()));
    connect(drawRing, SIGNAL(clicked()), SLOT(onDrawRing()));
    connect(drawDImage, SIGNAL(clicked()), SLOT(onDrawDImage()));
    connect(drawSImage, SIGNAL(clicked()), SLOT(onDrawSImage()));
    connect(startScaCircle, SIGNAL(clicked()), SLOT(onStartScanCircle()));

    connect(closeAll, SIGNAL(clicked()), SLOT(onCloseAll()));
}

TaskController::~TaskController()
{

}

void TaskController::onCloseAll()
{
    closeAllWin();
}

void TaskController::onShowClock(){
    if (myTimer != NULL) myTimer = new QTimer();
    if (NULL == fullscrClockList)
        fullscrClockList = new QList <FullScreenClock*>;
    else fullscrClockList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);

#ifdef DEBUG
            qDebug() << "Test Screen:" << i;
#endif
//            FullScreenClock *w = t->getScreenWidget();
            FullScreenClock * w = new FullScreenClock(screen);
            w->showFullScreen();
            fullscrClockList->append(w);
            connect(myTimer, SIGNAL(timeout()), w, SLOT(drawWindow()));

//#ifdef DEBUG
//            finish = clock();
//            totalTime = (double)(finish - start)/(double)CLOCKS_PER_SEC;
//            qDebug() << "The total time is" << totalTime;
//#endif
        }
    }
    myTimer->start(10);
}

void TaskController::onStartScanCircle(){
#ifdef DEBUG
    qDebug() << "Entering onStartScanCircle";
#endif
    int radius = sCirRadInput->text().toInt();
    int red = sCirRInput->text().toInt();
    int green = sCirGInput->text().toInt();
    int blue = sCirBInput->text().toInt();
    QColor color(red, green, blue);
    int width = sCirLWInput->text().toInt();
    int interval = int (sCirInvInput->text().toDouble() * 1000);
//    if (NULL == mySCTimer) mySCTimer = new QTimer();
//    mySCTimer->start(interval);
    if (NULL == scanCircleList)
        scanCircleList = new QList <ScaningCircle*>;
    else scanCircleList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);

#ifdef DEBUG
            qDebug() << "Test Screen:" << i;
#endif
            ScaningCircle * w = new ScaningCircle(screen);
            w->setCircle(radius, width, color, interval);
            w->showFullScreen();
            scanCircleList->append(w);
//            connect(mySCTimer, SIGNAL(timeout()), w, SLOT(repaint()));
        }
    }

#ifdef DEBUG
    qDebug() << "Ending onStartScanCircle";
#endif
}

void TaskController::onShowStructedLight(){
    int colorNum = readLightList(STRUCTEDLIGHTFILE);
    if (0 == colorNum) {
        qDebug() << "File error or no color in file. Exit!";
        return;
    }
#ifdef DEBUG
    qDebug() << "There are" << colorNum << "colors in file" << STRUCTEDLIGHTFILE;
#endif

    if (NULL == fullscrSLightList)
        fullscrSLightList = new QList <FullscrStructedLight*>;
    else fullscrSLightList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);
#ifdef DEBUG
            qDebug() << "Output from Screen:" << i;
#endif
            FullscrStructedLight * w = new FullscrStructedLight(screen);
            w->setColorList(colorList);
            w->setWidthList(widthList);
            w->setSLightStye(FullscrStructedLight::VSTRIP);
            w->showFullScreen();
            fullscrSLightList->append(w);

        }
    }
}

int TaskController::readLightList(QString filename)
{
    colorList = new QList <QColor>;
    widthList = new QList <int>;
    QFile colorFile(filename);
    if (!colorFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Color file error";
        return 0;
    }

    int i=0;
    while (!colorFile.atEnd()) {
        //Read a line
        QByteArray line = colorFile.readLine();
        QString newLine(QString::fromAscii(line).trimmed());
#ifdef DEBUG
        qDebug() << "Reading" << filename << "Line:" << i << newLine;
#endif
        QStringList newList = newLine.split(",", QString::SkipEmptyParts);
        colorList->append(QColor(newList.at(0).toInt(),
                                 newList.at(1).toInt(),
                                 newList.at(2).toInt()));
        widthList->append(newList.at(3).toInt());
#ifdef DEBUG
        qDebug() << "Reading color" << i << ":" << colorList->at(i) << "Width:" << widthList->at(i);
#endif
        i++;
    }

    return i;
}

void TaskController::onDrawCircle()
{
    //TODO
    int x = xInput->text().toInt();
    int y = yInput->text().toInt();
    int radius = radInput->text().toInt();
    int red = rInput->text().toInt();
    int green = gInput->text().toInt();
    int blue = bInput->text().toInt();
    QColor color(red, green, blue);
    int width = widthInput->text().toInt();

    if (NULL == fullscrCircleList)
        fullscrCircleList = new QList <DrawCircle*>;
    else fullscrCircleList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);
#ifdef DEBUG
            qDebug() << "Output from Screen:" << i;
#endif
            DrawCircle * w = new DrawCircle(screen);
            w->setCircle(x, y, radius, width, color);
            w->setRing(false);
            w->showFullScreen();
            fullscrCircleList->append(w);
        }
    }
}

void TaskController::onDrawRing()
{
    //TODO
    int x = xInput->text().toInt();
    int y = yInput->text().toInt();
    int radius = radInput->text().toInt();
    int red = rInput->text().toInt();
    int green = gInput->text().toInt();
    int blue = bInput->text().toInt();
    QColor color(red, green, blue);
    int width = widthInput->text().toInt();

    if (NULL == fullscrCircleList)
        fullscrCircleList = new QList <DrawCircle*>;
    else fullscrCircleList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);
#ifdef DEBUG
            qDebug() << "Output from Screen:" << i;
#endif
            DrawCircle * w = new DrawCircle(screen);
            w->setCircle(x, y, radius, width, color);
            w->setRing(true);
            w->showFullScreen();
            fullscrCircleList->append(w);
//            connect(w, SIGNAL(escapeKeyPressed()), this, SLOT(closeAllWin()));
        }
    }
}

void TaskController::onDrawDImage()
{
    if (NULL == fullscrImageList)
        fullscrImageList = new QList <DrawImage*>;
    else fullscrImageList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);

#ifdef DEBUG
            qDebug() << "Test Screen:" << i;
#endif
            DrawImage * w = new DrawImage(screen);
            w->setImagePath("test.png");
            w->showFullScreen();
            fullscrImageList->append(w);
        }
    }
}

void TaskController::onDrawSImage()
{
    QString newPath = QFileDialog::getOpenFileName(this, tr("Open Image File"),
                                                   "/home",
                                                   tr("Images (*.png *.bmp *.jpg *.PNG *.BMP *.JPG)"));
    if (NULL == fullscrImageList)
        fullscrImageList = new QList <DrawImage*>;
    else fullscrImageList->clear();

    if (totalScreen >= 1)
    {
        //TODO
        for (int i=0; i<totalScreen; i++)
        {
            QWidget * screen = desktop->screen(i);

#ifdef DEBUG
            qDebug() << "Test Screen:" << i;
#endif
            DrawImage * w = new DrawImage(screen);
            if (newPath.length() > 0){
                w->setImagePath(newPath);
                w->showFullScreen();
            }
            fullscrImageList->append(w);
        }
    }
}


void TaskController::closeAllWin()
{
    //Clock
    if (fullscrClockList != NULL && !fullscrClockList->empty())
    {
#ifdef DEBUG
    qDebug() << "Widgets in fullscrClockList:" << fullscrClockList->count();
#endif
        for (int i=0; i<fullscrClockList->count(); i++)
        {
            fullscrClockList->at(i)->endThis();
        }
        fullscrClockList->clear();
#ifdef DEBUG
    qDebug() << "Widgets in fullscrClockList:" << fullscrClockList->count();
#endif
    }

    //Structured Light
    if (fullscrSLightList != NULL && !fullscrSLightList->empty())
    {
#ifdef DEBUG
    qDebug() << "Widgets in fullscrSLightList:" << fullscrSLightList->count();
#endif
        for (int i=0; i<fullscrSLightList->count(); i++)
        {
            fullscrSLightList->at(i)->endThis();
        }
        fullscrSLightList->clear();
#ifdef DEBUG
    qDebug() << "Widgets in fullscrClockList:" << fullscrSLightList->count();
#endif
    }

    //Circle
    if (fullscrCircleList != NULL && !fullscrCircleList->empty())
    {
#ifdef DEBUG
    qDebug() << "Widgets in fullscrCircleList:" << fullscrCircleList->count();
#endif
        for (int i=0; i<fullscrCircleList->count(); i++)
        {
            fullscrCircleList->at(i)->endThis();
        }
        fullscrCircleList->clear();
#ifdef DEBUG
    qDebug() << "Widgets in fullscrCircleList:" << fullscrCircleList->count();
#endif
    }

    //Image
    if (fullscrImageList != NULL && !fullscrImageList->empty())
    {
#ifdef DEBUG
    qDebug() << "Widgets in fullscrImageList:" << fullscrImageList->count();
#endif
        for (int i=0; i<fullscrImageList->count(); i++)
        {
            fullscrImageList->at(i)->endThis();
        }
        fullscrImageList->clear();
#ifdef DEBUG
    qDebug() << "Widgets in fullscrImageList:" << fullscrImageList->count();
#endif
    }

    //Scaning Circle
    if (scanCircleList != NULL && !scanCircleList->empty())
    {
#ifdef DEBUG
    qDebug() << "Widgets in scanCircleList:" << scanCircleList->count();
#endif
        for (int i=0; i<scanCircleList->count(); i++)
        {
            scanCircleList->at(i)->endThis();
        }
        scanCircleList->clear();
#ifdef DEBUG
    qDebug() << "Widgets in scanCircleList:" << scanCircleList->count();
#endif
    }
}
